package hub.gongshang.controller;

import hub.gongshang.vo.ApiResult;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import io.reactivex.Flowable;
import io.reactivex.schedulers.Schedulers;

import java.io.IOException;
import java.time.Duration;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

@RestController
@RequestMapping("test")
public class TestController {
    // 模拟数据库存储
    private static final List<Map<String, Object>> mockData = new ArrayList<>();
    private static int idCounter = 1;

    // 初始化模拟数据
    static {
        String[] states = {"成功", "失败", "进行中"};
        String[] addresses = {"广东省深圳市", "湖南省长沙市", "北京市朝阳区", "上海市浦东新区", "浙江省杭州市"};

        for (int i = 1; i <= 50; i++) {
            Map<String, Object> item = new HashMap<>();
            item.put("id", i);
            item.put("name", "用户" + i);
            item.put("money", String.format("%.2f", 1000 + Math.random() * 9000));
            item.put("state", states[i % 3]);
            item.put("date", LocalDate.now().minusDays(i).toString());
            item.put("address", addresses[i % 5]);
            item.put("thumb", "https://img.yzcdn.cn/vant/cat.jpeg");
            mockData.add(item);
        }
        idCounter = 51;
    }

    /**
     * Springboot接口联通测试
     *
     * @return
     */
    @GetMapping("test")
    public String test() {
        return "test";
    }

    /**
     * 测试统一结果返回-msg
     *
     * @return
     */
    @GetMapping("testReturnJson")
    public ApiResult<String> testReturnJson() {
        return ApiResult.success("统一返回测试");
    }

    /**
     * 测试统一结果返回-data
     *
     * @return
     */
    @GetMapping("testReturnJson2")
    public ApiResult<List<String>> testReturnJson2() {
        return ApiResult.success(List.of("1", "2"));
    }

    /**
     * 测试全局异常处理-参数缺失校验
     *
     * @param param
     * @return
     */
    @GetMapping("testParamRequire")
    public ApiResult<String> testParamRequire(@RequestParam(name = "param", required = true) String param) {
        return ApiResult.success("测试全局异常拦截");
    }

    /**
     * 测试接收微信请求
     *
     * @param requestBody
     * @return
     */
    @PostMapping("testWxRequest")
    public ApiResult<String> testWxRequest(@RequestBody Map<String, Object> requestBody) {

        // 打印接收到的所有参数
        System.out.println("=== 接收到反馈数据 ===");
        requestBody.forEach((key, value) -> {
            System.out.println(key + ": " + value);
        });
        System.out.println("====================");

        // 或者逐个获取打印
        String content = (String) requestBody.get("content");
        String category = (String) requestBody.get("category");
        String openid = (String) requestBody.get("openid");
        String userName = (String) requestBody.get("userName");
        String timestamp = (String) requestBody.get("timestamp");

        System.out.println("内容: " + content);
        System.out.println("分类: " + category);
        System.out.println("OpenID: " + openid);
        System.out.println("用户名: " + userName);
        System.out.println("时间戳: " + timestamp);
        return ApiResult.success("success");
    }

    /**
     * 获取表格列表数据（支持分页和搜索）
     */
    @GetMapping("/tableList")
    public ApiResult<Map<String, Object>> getTableList(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(required = false) String name,
            @RequestParam(required = false) String address) {

        // 过滤数据
        List<Map<String, Object>> filteredData = new ArrayList<>(mockData);

        // 按名称搜索
        if (name != null && !name.trim().isEmpty()) {
            filteredData.removeIf(item -> !item.get("name").toString().contains(name));
        }

        // 按地址搜索
        if (address != null && !address.trim().isEmpty()) {
            filteredData.removeIf(item -> !item.get("address").toString().contains(address));
        }

        // 分页处理
        int total = filteredData.size();
        int startIndex = (page - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, total);

        List<Map<String, Object>> pageData = new ArrayList<>();
        if (startIndex < total) {
            pageData = filteredData.subList(startIndex, endIndex);
        }

        // 构建响应
        Map<String, Object> response = new HashMap<>();
        response.put("code", 200);
        response.put("message", "success");

        Map<String, Object> data = new HashMap<>();
        data.put("list", pageData);
        data.put("total", total);
        data.put("page", page);
        data.put("pageSize", pageSize);

        response.put("data", data);

        return ApiResult.success(response);
    }

    /**
     * 流式输出端点 - SSE (Server-Sent Events)
     * 模拟AI打字机效果的流式输出
     */
    @GetMapping(value = "/sseStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter sseStream(@RequestParam(defaultValue = "在编码的道路上，我们不断探索和学习。每一行代码都承载着我们的思想和创意。通过流式输出，我们可以实时地看到数据的流动，就像一场精彩的表演，每一个字符都是舞台上的演员，依次登场，为我们展现一个动态而生动的画面。") String content) {
        SseEmitter emitter = new SseEmitter(300000L); // 设置超时时间为5分钟

        // 在新线程中处理流式输出，避免阻塞主线程
        new Thread(() -> {
            try {
                // 发送初始事件，标记流开始
                emitter.send(SseEmitter.event()
                        .id("1")
                        .name("start")
                        .data("开始输出")
                        .build());

                // 逐字符输出，模拟打字机效果
                char[] chars = content.toCharArray();
                for (int i = 0; i < chars.length; i++) {
                    String character = String.valueOf(chars[i]);

                    // 发送单个字符
                    emitter.send(SseEmitter.event()
                            .id(String.valueOf(i + 2))
                            .name("message")
                            .data(character)
                            .build());

                    // 控制输出速度，每个字符间隔50-100毫秒
                    Thread.sleep(50 + Math.round(Math.random() * 50));

                }

                // 发送完成事件
                emitter.send(SseEmitter.event()
                        .id(String.valueOf(chars.length + 2))
                        .name("done")
                        .data("输出完成")
                        .build());

                // 完成发送
                emitter.complete();
            } catch (IOException | InterruptedException e) {
                emitter.completeWithError(e);
                e.printStackTrace();
            }
        }).start();

        return emitter;
    }


    /**
     * 使用WebFlux实现流式文本输出（类似打字机效果）
     * 返回Flux<String>，每个元素是一个字符
     */
    @GetMapping(value = "/webflux/stream-text", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamText(@RequestParam(defaultValue = "欢迎使用WebFlux流式传输！这是基于Reactor的响应式编程实现，能够高效处理大量并发请求，提供流畅的用户体验。") String content) {
        return Flux.fromArray(content.split(""))
                .delayElements(Duration.ofMillis(50)) // 每50毫秒发送一个字符
                .onBackpressureBuffer(); // 处理背压
    }

    /**
     * WebFlux日志流端点
     * 持续输出模拟日志，支持客户端中断
     */
    @GetMapping(value = "/webflux/log-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> logStream() {
        return Flux.interval(Duration.ofMillis(500))
                .map(sequence -> {
                    String[] logLevels = {"INFO", "DEBUG", "WARN", "ERROR"};
                    String[] messages = {
                            "Processing request...",
                            "Database query executed",
                            "Cache hit",
                            "User authentication passed",
                            "Data validation completed",
                            "Response generated",
                            "Request completed successfully"
                    };
                    String level = logLevels[(int) (sequence % logLevels.length)];
                    String message = messages[(int) (sequence % messages.length)];
                    String timestamp = java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("HH:mm:ss.SSS"));
                    return String.format("[%s] %s - %s", timestamp, level, message);
                })
                .onBackpressureBuffer();
    }

    /**
     * 流式输出Markdown内容（纯文本，不需要标记格式）
     * 包含代码块、链接、图片、引用等所有Markdown元素
     * 前端使用markdown-it库统一解析渲染
     */
    @GetMapping(value = "/rich-stream/markdown-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter streamMarkdown() {
        SseEmitter emitter = new SseEmitter(300000L);

        new Thread(() -> {
            try {
                // 发送开始事件
                emitter.send(SseEmitter.event()
                        .id("0")
                        .name("start")
                        .data("")
                        .build());

                // 纯Markdown内容（完整的内容）
                String markdown = "# 🚀 AI流式输出完全指南\n\n" +
                        "## 核心特性\n" +
                        "这是一个展示**纯Markdown流式输出**的完整示例。前端无需任何格式识别，直接使用markdown-it库一次性渲染！\n\n" +
                        "### 代码块示例\n" +
                        "```java\n" +
                        "public class StreamExample {\n" +
                        "    public static void main(String[] args) {\n" +
                        "        System.out.println(\"Hello, Stream!\");\n" +
                        "    }\n" +
                        "}\n" +
                        "```\n\n" +
                        "### 链接示例\n" +
                        "你可以在流式内容中包含[MDN Web Docs](https://developer.mozilla.org)这样的链接。\n" +
                        "也可以链接到[百度搜索](https://www.baidu.com)。\n\n" +
                        "### 图片展示\n" +
                        "![示例图片](https://s3.bmp.ovh/imgs/2023/07/04/16a0b46418bf12ed.jpg)\n\n" +
                        "### 列表内容\n" +
                        "- SSE (Server-Sent Events) - 简单易用\n" +
                        "- WebSocket - 双向通信\n" +
                        "- WebFlux + Flux - 高性能响应式\n" +
                        "- gRPC Streaming - 高效传输\n\n" +
                        "### 引用块\n" +
                        "> 前端无需标记，纯Markdown文本流更简洁、更通用、更像真实AI！\n\n" +
                        "### 代码块2\n" +
                        "```python\n" +
                        "def hello_world():\n" +
                        "    print('Hello, Markdown!')\n" +
                        "\n" +
                        "if __name__ == '__main__':\n" +
                        "    hello_world()\n" +
                        "```\n\n" +
                        "---\n\n" +
                        "**流式输出完成！** 这个示例展示了纯Markdown方案的简洁性。";

                // ✅ 逐字符发送，实现真正的打字机效果
                StringBuilder content = new StringBuilder();
                char[] chars = markdown.toCharArray();
                for (int i = 0; i < chars.length; i++) {
                    content.append(chars[i]);

                    // 每个字符都发送一次
                    emitter.send(SseEmitter.event()
                            .id(String.valueOf(i + 1))
                            .name("message")
                            .data(content.toString())
                            .build());

                    // ✅ 控制速度：50-100ms，产生打字机效果
                    Thread.sleep(30 + (int) (Math.random() * 50));
                }

                // 发送完成事件
                emitter.send(SseEmitter.event()
                        .id(String.valueOf(chars.length + 1))
                        .name("done")
                        .data("")
                        .build());

                emitter.complete();
            } catch (IOException | InterruptedException e) {
                emitter.completeWithError(e);
            }
        }).start();

        return emitter;
    }

    /**
     * 调用真实的通义千问API - 流式输出
     * 使用官方SDK的streamCall方法，支持流式传输
     * 需要配置环境变量：DASHSCOPE_API_KEY
     */
    @GetMapping(value = "/ai/qwen-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter qwenStream(@RequestParam(defaultValue = "介绍一下自己") String question) {
        SseEmitter emitter = new SseEmitter(300000L);

        new Thread(() -> {
            try {
                // 获取API Key
                String apiKey = System.getenv("DASHSCOPE_API_KEY");
                if (apiKey == null || apiKey.isEmpty()) {
                    String errorMsg = "❌ 未配置API KEY! 请设置环境变量: DASHSCOPE_API_KEY";
                    emitter.send(SseEmitter.event()
                            .name("error")
                            .data(errorMsg)
                            .build());
                    emitter.completeWithError(new RuntimeException(errorMsg));
                    return;
                }

                // 初始化 Generation 实例
                Generation gen = new Generation();
                CountDownLatch latch = new CountDownLatch(1);

                // 构建请求参数
                GenerationParam param = GenerationParam.builder()
                        .apiKey(apiKey)
                        .model("qwen-plus")  // 可选：qwen-turbo、qwen-max等
                        .messages(Arrays.asList(
                                Message.builder()
                                        .role(Role.USER.getValue())
                                        .content(question)
                                        .build()
                        ))
                        .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                        .incrementalOutput(true)  // 启用增量输出（流式）
                        .build();

                // 发送开始事件
                emitter.send(SseEmitter.event()
                        .name("start")
                        .data("正在调用通义千问API...")
                        .build());

                // 发起流式调用
                Flowable<com.alibaba.dashscope.aigc.generation.GenerationResult> result = gen.streamCall(param);

                StringBuilder fullContent = new StringBuilder();
                StringBuilder tokenInfo = new StringBuilder();

                result
                        .subscribeOn(Schedulers.io())
                        .observeOn(Schedulers.computation())
                        .subscribe(
                                // onNext: 处理每个响应片段
                                message -> {
                                    try {
                                        if (message.getOutput() != null && message.getOutput().getChoices().size() > 0) {
                                            String content = message.getOutput().getChoices().get(0).getMessage().getContent();
                                            String finishReason = message.getOutput().getChoices().get(0).getFinishReason();

                                            // 发送内容
                                            fullContent.append(content);

                                            // 发送单个字符，实现打字机效果
                                            for (char c : content.toCharArray()) {
                                                emitter.send(SseEmitter.event()
                                                        .name("message")
                                                        .data(String.valueOf(c))
                                                        .build());
                                                try {
                                                    Thread.sleep(20 + (int) (Math.random() * 30));
                                                } catch (InterruptedException e) {
                                                    Thread.currentThread().interrupt();
                                                }
                                            }

                                            // 当finishReason不为null时，表示是最后一个chunk
                                            if (finishReason != null && !"null".equals(finishReason)) {
                                                if (message.getUsage() != null) {
                                                    tokenInfo.append(String.format("\n--- Token使用统计 ---\n输入Tokens: %d\n输出Tokens: %d\n总Tokens: %d",
                                                            message.getUsage().getInputTokens(),
                                                            message.getUsage().getOutputTokens(),
                                                            message.getUsage().getTotalTokens()));
                                                }
                                            }
                                        }
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                },
                                // onError: 处理错误
                                error -> {
                                    try {
                                        String errorMsg = "❌ API请求失败: " + error.getMessage();
                                        emitter.send(SseEmitter.event()
                                                .name("error")
                                                .data(errorMsg)
                                                .build());
                                        emitter.completeWithError(error);
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                    latch.countDown();
                                },
                                // onComplete: 完成回调
                                () -> {
                                    try {
                                        if (tokenInfo.length() > 0) {
                                            emitter.send(SseEmitter.event()
                                                    .name("message")
                                                    .data(tokenInfo.toString())
                                                    .build());
                                        }
                                        emitter.send(SseEmitter.event()
                                                .name("done")
                                                .data("✅ 回复完成")
                                                .build());
                                        emitter.complete();
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                    latch.countDown();
                                }
                        );

                // 等待异步任务完成
                latch.await();

            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        }).start();

        return emitter;
    }

}
